package com.absorbx.jcr.dao.impl;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.ocm.exception.JcrMappingException;
import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
import org.apache.jackrabbit.ocm.manager.impl.ObjectIterator;
import org.apache.jackrabbit.ocm.query.Filter;
import org.apache.jackrabbit.ocm.query.Query;
import org.apache.jackrabbit.ocm.query.QueryManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springmodules.jcr.jackrabbit.ocm.JcrMappingCallback;
import org.springmodules.jcr.jackrabbit.ocm.JcrMappingTemplate;

import com.absorbx.jcr.dao.ContentDao;

public class ContentDaoJcrImpl implements ContentDao {
    protected final Log log = LogFactory.getLog(ContentDaoJcrImpl.class);
    @Autowired
    @Qualifier("jcrMappingTemplate")
    protected JcrMappingTemplate jcrMappingTemplate = null;

    public void setJcrMappingTemplate(JcrMappingTemplate jcrMappingTemplate) {
        this.jcrMappingTemplate = jcrMappingTemplate;
    }


    @SuppressWarnings("unchecked")
    public Collection getAll(final Class clazz) {
        QueryManager queryManager = jcrMappingTemplate.createQueryManager();
        Filter filter = queryManager.createFilter(clazz);
        Query query = queryManager.createQuery(filter);
        return (Collection) jcrMappingTemplate.getObjects(query);
    }

    public <T> Collection<T> doPagination(final Class<T> clazz, String scope,
            final long offset, final long limit) {
        QueryManager queryManager = jcrMappingTemplate.createQueryManager();
        Filter filter = queryManager.createFilter(clazz);
        filter.setScope(scope);
        final Query query = queryManager.createQuery(filter);
        final Collection<T> result = new ArrayList<T>();
        jcrMappingTemplate.execute(new JcrMappingCallback() {

            public Object doInJcrMapping(ObjectContentManager manager)
                    throws JcrMappingException {

                ObjectIterator iterator = (ObjectIterator) manager
                        .getObjectIterator(query);
                long size = iterator.getSize();
                long position = iterator.getPosition();

                iterator.skip(offset);

                for (long i = offset; i < offset + limit; i++) {
                    result.add(clazz.cast(iterator.next()));

                }
                System.err.println("size:" + size + "p:" + position);

                return result;

            }
        });

        return result;
    }

    public Object save(final Object object) {
        jcrMappingTemplate.execute(new JcrMappingCallback() {

            public Object doInJcrMapping(ObjectContentManager manager)
                    throws JcrMappingException {

                manager.insert(object);
                manager.save();

                return null;

            }
        });
        return object;
    }

    public Object update(final Object object) {
        jcrMappingTemplate.execute(new JcrMappingCallback() {

            public Object doInJcrMapping(ObjectContentManager manager)
                    throws JcrMappingException {
                manager.update(object);
                manager.save();
                return object;
            }
        });
        return object;
    }

    public void remove(final Object object) {
        jcrMappingTemplate.execute(new JcrMappingCallback() {

            public Object doInJcrMapping(ObjectContentManager manager)
                    throws JcrMappingException {
                manager.remove(object);
                manager.save();
                return null;
            }
        });
    }

    public Object findByPath(String path) {
        return jcrMappingTemplate.getObject(path);
    }

    @Override
    public Object findByUUID(final String uuid) {
        return jcrMappingTemplate.execute(new JcrMappingCallback() {

            public Object doInJcrMapping(ObjectContentManager manager)
                    throws JcrMappingException {

                return manager.getObjectByUuid(uuid);
            }
        });
    }

    @SuppressWarnings("unchecked")
    @Override
    public Collection getAllInScope(String scope, final Class clazz) {
        QueryManager queryManager = jcrMappingTemplate.createQueryManager();
        Filter filter = queryManager.createFilter(clazz);
        filter.setScope(scope);

        Query query = queryManager.createQuery(filter);
        return (Collection) jcrMappingTemplate.getObjects(query);
    }

    @Override
    public void removeByPath(final String path) {
        jcrMappingTemplate.execute(new JcrMappingCallback() {

            public Object doInJcrMapping(ObjectContentManager manager)
                    throws JcrMappingException {
                Object obj = manager.getObject(path);

                if (obj != null) {
                    manager.remove(path);
                    manager.save();
                }
                return null;
            }
        });

    }

    @SuppressWarnings("unchecked")
	@Override
    public Collection findByProperty(Class clazz, String scope,
            String propertyName, String value) {
        QueryManager queryManager = jcrMappingTemplate.createQueryManager();
        Filter filter = queryManager.createFilter(clazz);
        if (scope == null || scope == "") {
            scope = "//";
        }
        filter.setScope(scope);
        filter.addEqualTo(propertyName, value);
        Query query = queryManager.createQuery(filter);
        Collection result = jcrMappingTemplate.getObjects(query);
        return (Collection) result;
    }

  

}
